package ws.jdbc.concurrent.driver.sqlserver.cursor.shared;

import ws.jdbc.concurrent.driver.sqlserver.ResultSetCursor;
import ws.jdbc.concurrent.driver.sqlserver.Messages;
import java.sql.Date;
import java.sql.SQLException;
import java.util.concurrent.locks.ReentrantLock;
import ws.jdbc.concurrent.driver.sqlserver.CResultSet;
import ws.jdbc.concurrent.driver.sqlserver.tds.TDSMessage;

/**
 * This class provides the functionality of a result set cursor with shared cache.
 * 
 * @author Wilson Santos, 36228 <wilson.santos@ua.pt>
 */
public abstract class CursorSharedCache extends ResultSetCursor {

  protected CResultSet crs;

  public CursorSharedCache(final TDSMessage message, final CResultSet crs, final ReentrantLock lock) throws SQLException {
    super(message, crs, lock);
    this.crs = crs;
  }

  @Override
  public boolean next() throws SQLException {
    boolean ret = false;
    lock.lock();
    try {
      ++currentRow;
      ret = crs.absolute(currentRow);
    } finally {
      lock.unlock();
    }
    return ret;
  }

  @Override
  public int getInt(int columnIndex) throws SQLException {
    final Integer ret;
    lock.lock();
    try {
      crs.restoreContext(currentRow);
      ret = crs.getInt(columnIndex);
    } finally {
      lock.unlock();
    }
    return ret;
  }

  @Override
  public String getString(int columnIndex) throws SQLException {
    final String ret;
    lock.lock();
    try {
      crs.restoreContext(currentRow);
      ret = crs.getString(columnIndex);
    } finally {
      lock.unlock();
    }
    return ret;
  }

  @Override
  public double getDouble(int columnIndex) throws SQLException {
    final Double ret;
    lock.lock();
    try {
      crs.restoreContext(currentRow);
      ret = crs.getDouble(columnIndex);
    } finally {
      lock.unlock();
    }
    return ret;
  }

  @Override
  public Date getDate(int columnIndex) throws SQLException {
    final Date ret;
    lock.lock();
    try {
      crs.restoreContext(currentRow);
      ret = crs.getDate(columnIndex);
    } finally {
      lock.unlock();
    }
    return ret;
  }

  @Override
  public void insertRow() throws SQLException {
    if (currentRow != ROW_INSERT) {
      cancelRowUpdates();
      throw new SQLException(Messages.msg_is_not_on_insert_row);
    }
    message.cursorInsert(tdsResultSet.getCursor(), updateValues);
    lastRow.incrementAndGet();
    cancelRowUpdates();
  }

  @Override
  public void updateRow() throws SQLException {
    lock.lock();
    try {
      crs.restoreContext(currentRow, updateValues);
      crs.updateRow();
      crs.cancelRowUpdates();
    } finally {
      lock.unlock();
    }
  }

  @Override
  public void refreshRow() throws SQLException {
    lock.lock();
    try {
      crs.restoreContext(currentRow);
      crs.refreshRow();
    } finally {
      lock.unlock();
    }
  }


}
